//|||||||||||||||||||||||||||||||||||||||||||||||

#include "GameState.hpp"
#include "OgreMeshManager.h"
#include "AdvancedOgreFramework.hpp"

//|||||||||||||||||||||||||||||||||||||||||||||||

//paged geometry
#include "PagedGeometry/PagedGeometryConfig.h"
//Include PagedGeometry headers that will be needed
#include "PagedGeometry/PagedGeometry.h"
#include "PagedGeometry/BatchPage.h"
#include "PagedGeometry/ImpostorPage.h"

//Include "HeightFunction.h", a header that provides some useful functions for quickly and easily
//getting the height of the terrain at a given point.
#include "PagedGeometry/HeightFunction.h"
//[NOTE] Remember that this "HeightFunction.h" file is not related to the PagedGeometry library itself
//in any way. It's simply a utility that's included with all these examples to make getting the terrain
//height easy. You can use it in your games/applications if you want, although if you're using a
//collision/physics library with a faster alternate, you may use that instead.

//|||||||||||||||||||||||||||||||||||||||||||||||

using namespace Ogre;
using namespace OgreBulletCollisions;
using namespace OgreBulletDynamics;

#define CUBE_HALF_EXTENTS 1

//|||||||||||||||||||||||||||||||||||||||||||||||

	static float	gMaxEngineForce = 3000.f;

	static float	gSteeringIncrement = 0.04f;
	static float	gSteeringClamp = 0.8f;

	static float	gWheelRadius = 0.5f;
	static float	gWheelWidth = 0.4f;

	static float	gWheelFriction = 1e30f;//1000;//1e30f;
	static float	gSuspensionStiffness = 20.f;
	static float	gSuspensionDamping = 2.3f;
	static float	gSuspensionCompression = 4.4f;

	static float	gRollInfluence = 0.1f;//1.0f;
	static float    gSuspensionRestLength = 0.6f;
	static float    gMaxSuspensionTravelCm = 500.0;
	static float    gFrictionSlip = 10.5;

GameState::GameState()
{
	m_bQuit=false;
	m_CarPosition = Ogre::Vector3(200,80,200);
	mNumEntitiesInstanced = 0;
	m_Gravity=9.8f;
	terrainBodyRestitution  = 0.1f;
	terrainBodyFriction     = 0.8f;
	//cube that has physics
	bounds= Ogre::AxisAlignedBox(Ogre::Vector3 (-10000, -10000, -10000), Ogre::Vector3 (10000,  10000,  10000));
	mTerrainShape=NULL;
	defaultTerrainBody=NULL;
}

void GameState::enter()
{
	//create SceneMgr
    m_pSceneMgr = OgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_EXTERIOR_CLOSE, "GameSceneMgr");
    
	//light
	Ogre::Light* directionalLight = m_pSceneMgr->createLight("directionalLight");
    directionalLight->setType(Ogre::Light::LT_DIRECTIONAL);
    directionalLight->setDiffuseColour(Ogre::ColourValue(.25, .25, 0));
    directionalLight->setSpecularColour(Ogre::ColourValue(.25, .25, 0));
	directionalLight->setDirection(Ogre::Vector3( 0, -1, 1 ));

	//cameras
    m_pCamera = m_pSceneMgr->createCamera("RallyCam");
	m_pCamera->setPosition(Ogre::Vector3(0,0,0));
    m_pCamera->lookAt(Ogre::Vector3(0,0,0));

	//viewport
	OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);
    OgreFramework::getSingletonPtr()->m_pViewport->setBackgroundColour(Ogre::ColourValue(0,0,0));
    // Alter the camera aspect ratio to match the viewport
    m_pCamera->setAspectRatio(Ogre::Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualWidth()) / Ogre::Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualHeight()));

	//load terrain
	m_pSceneMgr->setWorldGeometry("terrain.cfg");
	//initialize bullet
	bullet();

	//PagedGeometry
	createVeg();
	//createPart();

}

void GameState::bullet()
{
	//Direction of the gravity
	gravityVector=Ogre::Vector3(0,-m_Gravity,0);
	//create DynamicsWorld
	mWorld = new OgreBulletDynamics::DynamicsWorld(m_pSceneMgr, bounds, gravityVector);
	
	//Debug info display tool.
	//debugDrawer = new OgreBulletCollisions::DebugDrawer();
	//debugDrawer->setDrawWireframe(true);   // we want to see the Bullet containers
	//mWorld->setDebugDrawer(debugDrawer);
	//mWorld->setShowDebugShapes(true);
	//SceneNode *node2 = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("debugDrawer", Ogre::Vector3::ZERO);
	//node2->attachObject(static_cast <SimpleRenderable *> (debugDrawer));

	//get terrain.cfg info to make the terrain shape
	Ogre::ConfigFile config;
	config.load("terrain.cfg");
    unsigned page_size = Ogre::StringConverter::parseUnsignedInt(config.getSetting( "PageSize" ));
    Ogre::Vector3 terrainScale(Ogre::StringConverter::parseReal( config.getSetting( "PageWorldX" ) ) / (page_size-1),
                                Ogre::StringConverter::parseReal( config.getSetting( "MaxHeight" ) ),
                                Ogre::StringConverter::parseReal( config.getSetting( "PageWorldZ" ) ) / (page_size-1));
    Ogre::String terrainfileName = config.getSetting( "Heightmap.image" );
    float *heights = new float [page_size*page_size];	
    Ogre::Image terrainHeightMap;
    terrainHeightMap.load(terrainfileName, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);        
    for(unsigned y = 0; y < page_size; ++y)
    {
        for(unsigned x = 0; x < page_size; ++x)
        {
            Ogre::ColourValue color = terrainHeightMap.getColourAt(x, y, 0);
            heights[x + y * page_size] = color.r;
        }
    }
	
	//Make the Terrain shape
	mTerrainShape=new OgreBulletCollisions::HeightmapCollisionShape(page_size,page_size,terrainScale,heights,true);
	defaultTerrainBody = new OgreBulletDynamics::RigidBody("Terrain", mWorld);
    Ogre::Vector3 terrainShiftPos( (terrainScale.x * (page_size - 1) / 2), \
                                    0,
                                    (terrainScale.z * (page_size - 1) / 2));
    terrainShiftPos.y = terrainScale.y / 2 * terrainScale.y;
	Ogre::SceneNode* pTerrainNode = m_pSceneMgr->getRootSceneNode ()->createChildSceneNode ();
	defaultTerrainBody->setStaticShape (pTerrainNode, mTerrainShape, terrainBodyRestitution, terrainBodyFriction, terrainShiftPos);
	mBodies.push_back(defaultTerrainBody);
	mShapes.push_back(mTerrainShape);

	//Initialize wheel variables
    for (int i = 0; i < 4; i++)
    {
		mWheelsEngine[i] = i;
        mWheelsSteerable[i] = i;
    }
    //
	mWheelsEngineCount = 2;
    mWheelsSteerableCount = 2;

    mWheelEngineStyle = 0;
    mWheelSteeringStyle = 0;
    mSteeringLeft = false;
    mSteeringRight = false;
	mSteeringCenter=true;
    mEngineForce = 0;
    mSteering = 0;

	//Initialize Chassis Variables
	chassisShift=Ogre::Vector3(0, 1.0f, 0);
	connectionHeight = 0.7f;

	//Create Chassis entity and Node
    mChassis = m_pSceneMgr->createEntity(
            "chassis" + StringConverter::toString(mNumEntitiesInstanced++),
            "chassis.mesh");
    node = m_pSceneMgr->getRootSceneNode ()->createChildSceneNode ();
    SceneNode *chassisnode = node->createChildSceneNode ();
    chassisnode->attachObject (mChassis);
    chassisnode->setPosition (chassisShift);
	mChassis->setCastShadows(true);
    BoxCollisionShape* chassisShape = new BoxCollisionShape(Ogre::Vector3(1.f,0.75f,2.1f));
    CompoundCollisionShape* compound = new CompoundCollisionShape();
    compound->addChildShape(chassisShape, chassisShift);

	//Create the WheeledRigidBody mCarChassis
    mCarChassis = new WheeledRigidBody("carChassis", mWorld);
    mCarChassis->setShape (node, compound, 0.6f, 0.6f, 800, m_CarPosition, Quaternion::IDENTITY);
    mCarChassis->setDamping(0.2f, 0.2f);
    mCarChassis->disableDeactivation ();
    
	//Create Suspension
	mTuning = new VehicleTuning(
        gSuspensionStiffness,
        gSuspensionCompression,
        gSuspensionDamping,
        gMaxSuspensionTravelCm,
        gFrictionSlip);
	
	//Create VehicleRayCaster
    mVehicleRayCaster = new VehicleRayCaster(mWorld);
    mVehicle = new RaycastVehicle(mCarChassis, mTuning, mVehicleRayCaster);
	int rightIndex = 0;
    int upIndex = 1;
    int forwardIndex = 2;
    mVehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex);

	//Create Wheel Entity and Nodes
    Ogre::Vector3 wheelDirectionCS0(0,-1,0);
    Ogre::Vector3 wheelAxleCS(-1,0,0);
    for (int i = 0; i < 4; i++)
    {
        mWheels[i] = m_pSceneMgr->createEntity(
            "wheel" + StringConverter::toString(mNumEntitiesInstanced++),
            "wheel.mesh");

   		mWheels[i]->setCastShadows(true);

        mWheelNodes[i] = m_pSceneMgr->getRootSceneNode ()->createChildSceneNode ();
        mWheelNodes[i]->attachObject (mWheels[i]);

    }
    
	//
    bool isFrontWheel = true;

	//ConnectionPoint in the front wheel
    Ogre::Vector3 connectionPointCS0 (
        CUBE_HALF_EXTENTS-(0.3*gWheelWidth),
        connectionHeight,
        2*CUBE_HALF_EXTENTS-gWheelRadius);

	//AddWheel to the RayCastVehicle mVehicle
    mVehicle->addWheel(
        mWheelNodes[0],
        connectionPointCS0,
        wheelDirectionCS0,
        wheelAxleCS,
        gSuspensionRestLength,
        gWheelRadius,
        isFrontWheel, gWheelFriction, gRollInfluence);

	//ConnectionPoint in the front wheel
    connectionPointCS0 = Ogre::Vector3(
        -CUBE_HALF_EXTENTS+(0.3*gWheelWidth),
        connectionHeight,
        2*CUBE_HALF_EXTENTS-gWheelRadius);

	//AddWheel to the RayCastVehicle mVehicle
    mVehicle->addWheel(
        mWheelNodes[1],
        connectionPointCS0,
        wheelDirectionCS0,
        wheelAxleCS,
        gSuspensionRestLength,
        gWheelRadius,
        isFrontWheel, gWheelFriction, gRollInfluence);

    //
    isFrontWheel = false;

	//ConnectionPoint in the back wheel
	connectionPointCS0 = Ogre::Vector3(
        -CUBE_HALF_EXTENTS+(0.3*gWheelWidth),
        connectionHeight,
        -2*CUBE_HALF_EXTENTS+gWheelRadius);	
    
	//AddWheel to the RayCastVehicle mVehicle
	mVehicle->addWheel(
        mWheelNodes[2],
        connectionPointCS0,
        wheelDirectionCS0,
        wheelAxleCS,
        gSuspensionRestLength,
        gWheelRadius,
        isFrontWheel, gWheelFriction, gRollInfluence);

	//ConnectionPoint in the back wheel
    connectionPointCS0 = Ogre::Vector3(
        CUBE_HALF_EXTENTS-(0.3*gWheelWidth),
        connectionHeight,
        -2*CUBE_HALF_EXTENTS+gWheelRadius);

	//AddWheel to the RayCastVehicle mVehicle
    mVehicle->addWheel(
        mWheelNodes[3],
        connectionPointCS0,
        wheelDirectionCS0,
        wheelAxleCS,
        gSuspensionRestLength,
        gWheelRadius,
        isFrontWheel, gWheelFriction, gRollInfluence);
}

void GameState::exit()
{
	exitBullet();
	exitPagedGeometry();
    m_pSceneMgr->destroyCamera(m_pCamera);
    if(m_pSceneMgr)
        OgreFramework::getSingletonPtr()->m_pRoot->destroySceneManager(m_pSceneMgr);
	
}

void GameState::exitPagedGeometry()
{
	/*
	//Delete the TreeLoader2D instances
	delete m_pTrees>getPageLoader();
	delete m_pBushes->getPageLoader();
	*/
	//Delete the PagedGeometry instances
	//delete m_pTrees;
	delete m_pGrass;
	//delete m_pBushes;
	
	//Also delete the tree/bush entities
	//m_pSceneMgr->destroyEntity("Tree");
	m_pSceneMgr->destroyEntity("grass");
	//m_pSceneMgr->destroyEntity("Bush");
}

void GameState::exitBullet()
{

	// OgreBullet physic delete - RigidBodies
    std::deque<OgreBulletDynamics::RigidBody *>::iterator itBody = mBodies.begin();
    while (mBodies.end() != itBody)
    {   
        delete *itBody;
        ++itBody;
    }   
    // OgreBullet physic delete - Shapes
    std::deque<OgreBulletCollisions::CollisionShape *>::iterator itShape = mShapes.begin();
    while (mShapes.end() != itShape)
    {   
        delete *itShape;
        ++itShape;
    }
    mBodies.clear();
    mShapes.clear();
    delete mWorld->getDebugDrawer();
    mWorld->setDebugDrawer(0);
    delete mWorld;

}

void GameState::update(double timeSinceLastFrame)
{
    m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;

	updateBullet(timeSinceLastFrame);

	m_pGrass->update();

	//CameraUpdate  
	m_pCamera->setPosition(node->getPosition().x,node->getPosition().y+10.0f,node->getPosition().z-20.0f);
	m_pCamera->lookAt(Ogre::Vector3(node->getPosition().x,node->getPosition().y,node->getPosition().z+20.0f));
    m_pCamera->setNearClipDistance(5);

	//fNode2->setPosition(node->getPosition().x,node->getPosition().y,node->getPosition().z-1.0f);

    if(m_bQuit == true)
    {
        popAppState();
        return;
    }
	
}

void GameState::updateBullet(double timeSinceLastFrame)
{
    // update Bullet Physics animation
	mWorld->stepSimulation(timeSinceLastFrame);   
    
	// apply engine Force on relevant wheels
    for (int i = mWheelsEngine[0]; i < mWheelsEngineCount; i++)
    {
        mVehicle->applyEngineForce (mEngineForce, mWheelsEngine[i]);
    }

	//Turn the Wheels
    if (mSteeringLeft)
    {
        mSteering += gSteeringIncrement;
        if (mSteering > gSteeringClamp)
            mSteering = gSteeringClamp;
    }
    else if (mSteeringRight)
    {
        mSteering -= gSteeringIncrement;
        if (mSteering < -gSteeringClamp)
            mSteering = -gSteeringClamp;
    }
	if(mSteeringCenter)
	{
		mSteering=0.0f;	
	}

    // apply Steering on relevant wheels
    for (int i = mWheelsSteerable[0]; i < mWheelsSteerableCount; i++)
    {
        if (i < 2)
            mVehicle->setSteeringValue (mSteering, mWheelsSteerable[i]);
        else
            mVehicle->setSteeringValue (-mSteering, mWheelsSteerable[i]);
    }
}

bool GameState::keyPressed(const OIS::KeyEvent &keyEventRef)
{
    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
    {
		m_bQuit=true;
		return true;
    }

	if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_SPACE))
	{
		mCarChassis->applyForce(Ogre::Vector3(0.0f,6000.0f,1000.0f),m_CarPosition);
		return true;
	}

	if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_B))
          {
            //Shoot Wheels
			Ogre::Vector3 size = Ogre::Vector3::ZERO;
            // starting position of the box
			Ogre::Vector3 position = Ogre::Vector3(node->getPosition().x,node->getPosition().y+1.0f,node->getPosition().z+2.0f);
		
			// create an ordinary, Ogre mesh with texture
            Entity *entity = m_pSceneMgr->createEntity(
                "Box" + StringConverter::toString(mNumEntitiesInstanced),
                "wheel.mesh");            
            entity->setCastShadows(true);
            // we need the bounding box of the box to be able to set the size of the Bullet-box
            AxisAlignedBox boundingB = entity->getBoundingBox();
            size = boundingB.getSize(); 
			size /= 2.0f; 
            size *= 0.96f;   
            //entity->setMaterialName("Examples/BumpyMetal");
            SceneNode *node3 = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
            node3->attachObject(entity);
            node3->scale(1.0f, 1.0f, 1.0f);   
            size *= 1.0f;                         
            OgreBulletCollisions::BoxCollisionShape *sceneBoxShape = new OgreBulletCollisions::BoxCollisionShape(size);
            OgreBulletDynamics::RigidBody *defaultBody = new OgreBulletDynamics::RigidBody(
                "defaultBoxRigid" + StringConverter::toString(mNumEntitiesInstanced),
                mWorld);
            defaultBody->setShape(   node3,
                            sceneBoxShape,
                            0.6f,         // dynamic body restitution
                            0.6f,         // dynamic body friction
                            1.0f,          // dynamic bodymass
                            position,      // starting position of the box
                            Quaternion(180,0,0));// orientation of the box
            mNumEntitiesInstanced++;            
            defaultBody->setLinearVelocity(
                    m_pCamera->getDerivedDirection().normalisedCopy() * 60.0f ); // shooting speed
                // push the created objects to the deques
			mShapes.push_back(sceneBoxShape);
            mBodies.push_back(defaultBody);            
             
          }

    bool wheel_engine_style_change = false;
    bool wheel_steering_style_change = false;

	if( OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_LEFT))
	{
		mSteeringLeft = true;
		mSteeringCenter=false;
		return true;
	}
	if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
	{
		mSteeringRight = true;
		mSteeringCenter=false;
		return true;
	}
    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_DOWN))
	{
        mEngineForce = -gMaxEngineForce;
		return true;
	}
    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_UP))
	{
        mEngineForce = gMaxEngineForce;	
		return true;
	}
    if (wheel_engine_style_change)
    {
        for (int i = 0; i < 4; i++)
            mWheelsEngine[i] = 0;

        if (mWheelEngineStyle < 0)
            mWheelEngineStyle = 2;

        switch (mWheelEngineStyle)
        {
        case 0://front
            mWheelsSteerableCount = 2;
            mWheelsSteerable[0] = 0;
            mWheelsSteerable[1] = 1;  
            break;
        case 1://back
            mWheelsSteerableCount = 2;
            mWheelsSteerable[0] = 2;
            mWheelsSteerable[1] = 3;  
            break;
        case 2://4x4
            mWheelsSteerableCount = 4;
            mWheelsSteerable[0] = 0;
            mWheelsSteerable[1] = 1;  
            mWheelsSteerable[2] = 2;
            mWheelsSteerable[3] = 3; 
            break;
        default:
            assert(0);
            break;
        }
    }

    if (wheel_steering_style_change)
    {
        for (int i = 0; i < 4; i++)
            mWheelsSteerable[i] = 0;

        if (mWheelSteeringStyle < 0)
            mWheelSteeringStyle = 2;

        switch (mWheelSteeringStyle)
        {
        case 0://front
            mWheelsEngineCount = 2;
            mWheelsEngine[0] = 0;
            mWheelsEngine[1] = 1;  
            break;
        case 1://back
            mWheelsEngineCount = 2;
            mWheelsEngine[0] = 2;
            mWheelsEngine[1] = 3;  
            break;
        case 2://4x4
            mWheelsEngineCount = 4;
            mWheelsEngine[0] = 0;
            mWheelsEngine[1] = 1;  
            mWheelsEngine[2] = 2;
            mWheelsEngine[3] = 3; 
            break;
        default:
            assert(0);
            break;
        }
    }
	
    return true;
}

bool GameState::keyReleased(const OIS::KeyEvent &keyEventRef)
{
	OgreFramework::getSingletonPtr()->keyReleased(keyEventRef);
	if((keyEventRef.key == OIS::KC_LEFT)) 
	{
		mSteeringLeft = false;
		mSteeringCenter=true;
		return true;
	}
	if(keyEventRef.key ==OIS::KC_RIGHT)
	{
        mSteeringRight = false;
		mSteeringCenter=true;
		return true;
	}
    if(keyEventRef.key ==OIS::KC_DOWN)
	{ 
        mEngineForce = 0;
        return true;
	}
    if(keyEventRef.key ==OIS::KC_UP)
	{
        mEngineForce = 0;
		return true;
    }

    return true;
}

bool GameState::mouseMoved(const OIS::MouseEvent &arg)
{
	return true;
}

bool GameState::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	return true;
}

bool GameState::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	return true;
}

void GameState::createVeg()
{
	/*
	//-------------------------------------- LOAD TREES --------------------------------------
	//Create and configure a new PagedGeometry instance
	m_pTrees= new PagedGeometry();
	m_pTrees->setCamera(m_pCamera);	//Set the camera so PagedGeometry knows how to calculate LODs
	m_pTrees->setPageSize(80);	//Set the size of each page of geometry
	m_pTrees->setInfinite();		//Use infinite paging mode
	m_pTrees->addDetailLevel<BatchPage>(150, 50);		//Use batches up to 150 units away, and fade for 30 more units
	m_pTrees->addDetailLevel<ImpostorPage>(500, 50);	//Use impostors up to 400 units, and for for 50 more units

	//Create a new TreeLoader3D object
	TreeLoader3D *treeLoader = new TreeLoader3D(m_pTrees, TBounds(0, 0, 1500, 1500));
	m_pTrees->setPageLoader(treeLoader);	//Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance

	//Load a tree entity
	Entity *myEntity = m_pSceneMgr->createEntity("Tree", "tree2.mesh");

	//Setup the height function (so the Y values of trees can be calculated when they are placed on the terrain)
	HeightFunction::initialize(m_pSceneMgr);

	//Randomly place 20,000 copies of the tree on the terrain
	Vector3 position;
	Radian yaw;
	Real scale;
	for (int i = 0; i < 5000; i++){
		yaw = Degree(Math::RangeRandom(0, 360));

		position.x = Math::RangeRandom(0, 1500);
		position.z = Math::RangeRandom(0, 1500);
		position.y = HeightFunction::getTerrainHeight(position.x, position.z);

		scale = Math::RangeRandom(0.5f, 0.6f);

		treeLoader->addTree(myEntity, position, yaw, scale);
	}
	*/
	/*
	//-------------------------------------- LOAD BUSHES --------------------------------------
	//Create and configure a new PagedGeometry instance for bushes
	m_pBushes = new PagedGeometry(m_pCamera, 50);
	m_pBushes->addDetailLevel<BatchPage>(80, 50);

	//Create a new TreeLoader2D object for the bushes
	TreeLoader2D *bushLoader = new TreeLoader2D(m_pBushes, TBounds(0, 0, 1500, 1500));
	m_pBushes->setPageLoader(bushLoader);

	//Supply the height function to TreeLoader2D so it can calculate tree Y values
	HeightFunction::initialize(m_pSceneMgr);
	bushLoader->setHeightFunction(&HeightFunction::getTerrainHeight);

	//Load a bush entity
	Entity *myBush = m_pSceneMgr->createEntity("Bush", "Bush.mesh");

	//Randomly place 30,000 copies of the bush on the terrain
	for (int i = 0; i < 20000; i++){
		yaw = Degree(Math::RangeRandom(0, 360));
		position.x = Math::RangeRandom(0, 1500);
		position.z = Math::RangeRandom(0, 1500);
		scale = Math::RangeRandom(0.7f, 0.8f);

		bushLoader->addTree(myBush, position, yaw, scale);
	}
	*/
	//-------------------------------------- LOAD GRASS --------------------------------------
	//Create and configure a new PagedGeometry instance for grass
	m_pGrass = new PagedGeometry(m_pCamera, 50);
	m_pGrass->addDetailLevel<GrassPage>(150);

	//Create a GrassLoader object
	m_pGrassLoader = new GrassLoader(m_pGrass);
	m_pGrass->setPageLoader(m_pGrassLoader);	//Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance

	//Supply a height function to GrassLoader so it can calculate grass Y values
	HeightFunction::initialize(m_pSceneMgr);
	m_pGrassLoader->setHeightFunction(&HeightFunction::getTerrainHeight);

	//Add some grass to the scene with GrassLoader::addLayer()
	GrassLayer *l = m_pGrassLoader->addLayer("grass");

	//Configure the grass layer properties (size, density, animation properties, fade settings, etc.)
	l->setMinimumSize(2.0f, 2.0f);
	l->setMaximumSize(2.5f, 2.5f);
	l->setAnimationEnabled(true);		//Enable animations
	l->setSwayDistribution(10.0f);		//Sway fairly unsynchronized
	l->setSwayLength(0.5f);				//Sway back and forth 0.5 units in length
	l->setSwaySpeed(0.5f);				//Sway 1/2 a cycle every second
	l->setDensity(1.5f);				//Relatively dense grass
	l->setFadeTechnique(FADETECH_GROW);	//Distant grass should slowly raise out of the ground when coming in range
	l->setRenderTechnique(GRASSTECH_QUAD);	//Draw grass as scattered quads

	//[NOTE] This sets the color map, or lightmap to be used for grass. All grass will be colored according
	//to this texture. In this case, the colors of the terrain is used so grass will be shadowed/colored
	//just as the terrain is (this usually makes the grass fit in very well).
	l->setColorMap("terrain_texture2.jpg");

	//This sets the density map that will be used to determine the density levels of grass all over the
	//terrain. This can be used to make grass grow anywhere you want to; in this case it's used to make
	//grass grow only on fairly level ground (see densitymap.png to see how this works).
	l->setDensityMap("densitymap.png");

	//setMapBounds() must be called for the density and color maps to work (otherwise GrassLoader wouldn't
	//have any knowledge of where you want the maps to be applied). In this case, the maps are applied
	//to the same boundaries as the terrain.
	l->setMapBounds(TBounds(0, 0, 1500, 1500));	//(0,0)-(1500,1500) is the full boundaries of the terrain
	/*
	//-------------------------------------- LOAD TREES 2 --------------------------------------
	//Create and configure a new PagedGeometry instance
	m_pTrees2 = new PagedGeometry();
	m_pTrees2->setCamera(m_pCamera);	//Set the camera so PagedGeometry knows how to calculate LODs
	m_pTrees2->setPageSize(80);	//Set the size of each page of geometry
	m_pTrees2->setInfinite();		//Use infinite paging mode
	m_pTrees2->addDetailLevel<BatchPage>(150, 50);		//Use batches up to 150 units away, and fade for 30 more units
	m_pTrees2->addDetailLevel<ImpostorPage>(500, 50);	//Use impostors up to 400 units, and for for 50 more units

	//Create a new TreeLoader2D object
	TreeLoader2D *treeLoader2 = new TreeLoader2D(m_pTrees2, TBounds(0, 0, 1500, 1500));
	m_pTrees2->setPageLoader(treeLoader2);	//Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance

	//Supply a height function to TreeLoader2D so it can calculate tree Y values
	HeightFunction::initialize(m_pSceneMgr);
	treeLoader2->setHeightFunction(&HeightFunction::getTerrainHeight);

	//[NOTE] This sets the color map, or lightmap to be used for trees. All trees will be colored according
	//to this texture. In this case, the shading of the terrain is used so trees will be shadowed
	//just as the terrain is (this should appear like the terrain is casting shadows on the trees).
	//You may notice that TreeLoader2D / TreeLoader3D doesn't have a setMapBounds() function as GrassLoader
	//does. This is because the bounds you specify in the TreeLoader2D constructor are used to apply
	//the color map.
	treeLoader2->setColorMap("terrain_lightmap.jpg");

	//Load a tree entity
	Entity *myEntity2 = m_pSceneMgr->createEntity("Tree2", "tree2.mesh");

	//Randomly place 20,000 copies of the tree on the terrain
	Ogre::Vector3 position2 = Ogre::Vector3::ZERO;
	Radian yaw2;
	Real scale2;
	for (int i = 0; i < 20000; i++){
		yaw2 = Degree(Math::RangeRandom(0, 360));

		position2.x = Math::RangeRandom(0, 1500);
		position2.z = Math::RangeRandom(0, 1500);

		scale2 = Math::RangeRandom(0.9f, 1.1f);

		//[NOTE] Unlike TreeLoader3D, TreeLoader2D's addTree() function accepts a Vector2D position (x/z)
		//The Y value is calculated during runtime (to save memory) from the height function supplied (above)
		treeLoader2->addTree(myEntity2, position2, yaw2, scale2);
	}
	*/
}

void GameState::createPart()
{
	/*
SceneNode* mFountainNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
// fireworks
ParticleSystem* pSys = m_pSceneMgr->createParticleSystem(
"fountain1", "Examples/Fireworks");
// Point the fountain at an angle
SceneNode* fNode = mFountainNode->createChildSceneNode();
fNode->attachObject(pSys);

// Funciona
*/
// smoke
	/*
pSys2 = m_pSceneMgr->createParticleSystem(
"fountain2", "Examples/Smoke");
pSys2->getEmitter()->setDimensions(0.1f,0.1f);
pSys2->getEmitter(0)->setDirection(Ogre::Vector3(0.0f,0.0f,-1.0f));
// Point the fountain at an angle
fNode2 = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
fNode2->attachObject(pSys2);
fNode2->translate(m_CarPosition);
fNode2->scale(0.1f,0.1f,0.1f);
*/
/*
// Funciona?
	//rain
	ParticleSystem* pSys3 = m_pSceneMgr->createParticleSystem(
	"fountain3", "Examples/Water/Rain");
	
	// Point the fountain at an angle
	SceneNode* fNode3 = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
	fNode3->attachObject(pSys3);
	fNode3->translate(200,200,200);
	Ogre::ParticleEmitter *area=pSys3->addEmitter("Box");
       area->setDirection(Vector3(0,-1,0));
       area->setEmissionRate(900);
       //area->setTimeToLive(7);
       area->setColour(ColourValue::White);
       //((Ogre::BoxEmitter*)(area))->setWidth(300.0f);
       //((Ogre::BoxEmitter*)(area))->setHeight(300.0f);
       area->setParticleVelocity(50.0f);
       area->setAngle(Radian(0));
	   //((Ogre::BoxEmitter*)(area))->setDepth(0.0f);


	//rain
	ParticleSystem* pSys4 = m_pSceneMgr->createParticleSystem(
	"fountain4", "Examples/GreenyNimbus");
	// Point the fountain at an angle
	SceneNode* fNode4 = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
	fNode4->attachObject(pSys4);
	fNode4->translate(200,250,200);	
*/	

}